<?php

defined('_JEXEC') or die('Restricted access');

function GetSubFromEmail($subemail) {
  $db =& JFactory::getDBO();

  $query = 'SELECT * FROM `#__nspro_subs` WHERE `email` = "' . mysql_escape_string($subemail) . '"';
  $db->setQuery($query);
  $sub = $db->loadObject();

  return $sub;
}

function FilterNewsletterSmartText($mySubName, $mySubEmail, $nid, $mMessage, $subid = 0) {

  $php_allowed = false;

  $db =& JFactory::getDBO();
  
  $mySubName = htmlentities($mySubName, ENT_COMPAT, "UTF-8");
  $mySubEmail = htmlentities($mySubEmail, ENT_COMPAT, "UTF-8");

  // initialize links
  $mybase = str_replace('/administrator/', '/', JURI::base());
  $myLink = $mybase.'index.php?option=com_nspro&amp;layout=confirmunsub'.'&amp;u='.md5($mySubEmail);
  $myFTFLink = $mybase.'index.php?option=com_nspro&amp;task=forwardtofriend&amp;nid=' . $nid . '&amp;semail=' . $mySubEmail;
  $myEDLLink = $mybase.'index.php?option=com_nspro&amp;layout=editlists'.'&amp;u='.md5($mySubEmail);
  $myNSLLink = $mybase.'index.php?option=com_nspro&amp;layout=newsletterview&amp;nid=' . $nid . '&amp;semail=' . $mySubEmail;

  // Smart Text Subscriber
  $mMessage = str_replace('{subscriber_name}', $mySubName, $mMessage);
  $mMessage = str_replace('{subscriber_email}', $mySubEmail, $mMessage);
  $subnames = explode(' ', $mySubName);
  if (count($subnames) == 1) {
    $mMessage = str_replace('{subscriber_first_name}', $subnames[0], $mMessage);
    $mMessage = str_replace('{subscriber_last_name}', '', $mMessage);
  }
  else if (count($subnames) == 2) {
    $mMessage = str_replace('{subscriber_first_name}', $subnames[0], $mMessage);
    $mMessage = str_replace('{subscriber_last_name}', $subnames[1], $mMessage);
  }
  else if (count($subnames) == 3) {
    $mMessage = str_replace('{subscriber_first_name}', $subnames[0] . ' ' . $subnames[1], $mMessage);
    $mMessage = str_replace('{subscriber_last_name}', $subnames[2], $mMessage);
  }
  else {
    $mMessage = str_replace('{subscriber_first_name}', $subnames[0] . ' ' . $subnames[1], $mMessage);
    $mMessage = str_replace('{subscriber_last_name}', $subnames[2] . ' ' . $subnames[3], $mMessage);
  }

  // Smart Text Link
  $mMessage = str_replace('{link:FTF}', '<a href="'. $myFTFLink .'">', $mMessage);
  $mMessage = str_replace('{link:UNSUB}', '<a href="'. $myLink .'">', $mMessage);
  $mMessage = str_replace('{link:EDITLISTS}', '<a href="'. $myEDLLink .'">', $mMessage);
  $mMessage = str_replace('{link:NEWSLETTER}', '<a href="'. $myNSLLink .'">', $mMessage);
  $mMessage = str_replace('{/link}', '</a>', $mMessage);

  // Smart Text URL
  $mMessage = str_replace('{url:FTF}', $myFTFLink, $mMessage);
  $mMessage = str_replace('{url:UNSUB}', $myLink, $mMessage);
  $mMessage = str_replace('{url:EDITLISTS}', $myEDLLink, $mMessage);
  $mMessage = str_replace('{url:NEWSLETTER}', $myNSLLink, $mMessage);

  //Smart Text Email Opening Tracking
  $imgpart1 = '<img src="' . $mybase . 'index.php?option=com_nspro&task=email_tracking&clr=';
  $imgpart2 = '&amp;nid=' . $nid . '&amp;e=' . md5($mySubEmail) . '"/>';
  $mMessage = str_replace('{img:white}', $imgpart1.'white'.$imgpart2, $mMessage);
  $mMessage = str_replace('{img:black}', $imgpart1.'black'.$imgpart2, $mMessage);
  $mMessage = str_replace('{img:red}',   $imgpart1.'red'.$imgpart2,   $mMessage);
  $mMessage = str_replace('{img:green}', $imgpart1.'green'.$imgpart2, $mMessage);
  $mMessage = str_replace('{img:blue}',  $imgpart1.'blue'.$imgpart2,  $mMessage);

  //Smart Text Include Joomla! Article
    // Article Text
  while (JString::strpos($mMessage, '{include:article}') != false) {
    $charCount = JString::strpos($mMessage, '{include:article}');

    $myRelativeCount = JString::strpos($mMessage, '{/include}', $charCount);

    if ($myRelativeCount !== false) {
      $myPiece = JString::substr($mMessage, $charCount, ($myRelativeCount-$charCount));
      $myIdString = JString::substr($myPiece, 17, ($myRelativeCount-$charCount)-17);
      $myId = (int) $myIdString;

      $query = 'SELECT `id`, `introtext`, `fulltext` FROM `#__content` WHERE `id` = ' . mysql_escape_string($myId);
      $db->setQuery( $query );

      $myArticle = $db->loadRow();

      $mMessage = str_replace('{include:article}'. $myIdString .'{/include}', $myArticle[1]  . $myArticle[2], $mMessage);
    }
  }
    // Article Title
  while (JString::strpos($mMessage, '{include:articletitle}') != false) {
    $charCount = JString::strpos($mMessage, '{include:articletitle}');

    $myRelativeCount = JString::strpos($mMessage, '{/include}', $charCount);

    if ($myRelativeCount !== false) {
      $myPiece = JString::substr($mMessage, $charCount, ($myRelativeCount-$charCount));
      $myIdString = JString::substr($myPiece, 22, ($myRelativeCount-$charCount)-22);
      $myId = (int) $myIdString;

      $query = 'SELECT `id`, `title` FROM `#__content` WHERE `id` = ' . mysql_escape_string($myId);
      $db->setQuery( $query );

      $myArticle = $db->loadRow();

      $mMessage = str_replace('{include:articletitle}'. $myIdString .'{/include}', $myArticle[1], $mMessage);
    }
  }

    // Article Intro
  while (JString::strpos($mMessage, '{include:articleintro}') != false) {
    $charCount = JString::strpos($mMessage, '{include:articleintro}');

    $myRelativeCount = JString::strpos($mMessage, '{/include}', $charCount);

    if ($myRelativeCount !== false) {
      $myPiece = JString::substr($mMessage, $charCount, ($myRelativeCount-$charCount));
      $myIdString = JString::substr($myPiece, 22, ($myRelativeCount-$charCount)-22);
      $myId = (int) $myIdString;

      $query = 'SELECT `id`, `introtext`, `fulltext` FROM `#__content` WHERE `id` = ' . mysql_escape_string($myId);
      $db->setQuery( $query );

      $myArticle = $db->loadRow();

      $readmorelink = '<br/>' . '<a href="' . $mybase . 'index.php?option=com_content&id=' . $myArticle[0] . '">' .
                      JText::_('Read More') . '</a>';

      $mMessage = str_replace('{include:articleintro}'. $myIdString .'{/include}', $myArticle[1] . $readmorelink, $mMessage);
    }
  }

  //Smart Text - Include Extra Fields
  while (JString::strpos($mMessage, '{include:field}') != false) {
    $charCount = JString::strpos($mMessage, '{include:field}');

    $myRelativeCount = JString::strpos($mMessage, '{/include}', $charCount);

    if ($myRelativeCount !== false) {
      $myPiece = JString::substr($mMessage, $charCount, ($myRelativeCount-$charCount));
      $myIdString = JString::substr($myPiece, 15, ($myRelativeCount-$charCount)-15);
      $myId = (int) $myIdString;

      $query = 'SELECT `value` FROM `#__nspro_field_values` WHERE `subscriber_id` = "'.$subid.'" AND `field_id` = "' . mysql_escape_string($myId) . '"';
      $db->setQuery( $query );

      $myFieldValue = $db->loadRow();
      if (!$myFieldValue) {
        $myFieldValue = array();
        $myFieldValue[0] = '';
      }

      $mMessage = str_replace('{include:field}'. $myIdString .'{/include}', $myFieldValue[0], $mMessage);
    }
  }

  // Load Modules in Newsletter
  while (JString::strpos($mMessage, '{include:module}') != false) {
    $charCount = JString::strpos($mMessage, '{include:module}');

    $myRelativeCount = JString::strpos($mMessage, '{/include}', $charCount);

    if ($myRelativeCount !== false) {
      $myPiece = JString::substr($mMessage, $charCount, ($myRelativeCount-$charCount));
      $myIdString = JString::substr($myPiece, 16, ($myRelativeCount-$charCount)-16);

      $contents = file_get_contents($mybase.'index.php?option=com_nspro&task=getmodule&modid=' . $myIdString);

      $mMessage = str_replace('{include:module}'. $myIdString .'{/include}', $contents, $mMessage);
    }
  }

  while (JString::strpos($mMessage, '{include:moduleposition}') != false) {
    $charCount = JString::strpos($mMessage, '{include:moduleposition}');

    $myRelativeCount = JString::strpos($mMessage, '{/include}', $charCount);

    if ($myRelativeCount !== false) {
      $myPiece = JString::substr($mMessage, $charCount, ($myRelativeCount-$charCount));
      $myPosition = JString::substr($myPiece, 24, ($myRelativeCount-$charCount)-24);

      $contents = file_get_contents($mybase.'index.php?option=com_nspro&task=getmodules&pos=' . $myPosition);

      $mMessage = str_replace('{include:moduleposition}'. $myPosition .'{/include}', $contents, $mMessage);
    }
  }
  
  // Random Content
  while (JString::strpos($mMessage, '{random:') != false) {
    $charCount = JString::strpos($mMessage, '{random:');

    $myrate = JString::substr($mMessage, $charCount+8, (JString::strpos($mMessage, '}', $charCount)-$charCount-8)); 
    $myRelativeCount = JString::strpos($mMessage, '{/random}', $charCount);
    
    if ($myRelativeCount !== false) {
      $strlength = 9 + strlen($myrate); // 9 instead of 8, because we include the closing }
      $myRandomPart = JString::substr($mMessage, $charCount+$strlength, ($myRelativeCount-$charCount-$strlength));

			$mypercentage = rtrim($myrate, '%');
			$myrandom = mt_rand(0, 100);
			if ($myrandom > $mypercentage) {
				$myoutput = '';
			}
			else {
        $myoutput = $myRandomPart;
			}
      
      $mMessage = str_replace('{random:'.$myrate.'}'.$myRandomPart.'{/random}', $myoutput, $mMessage);
    }
  }
  
  if ($php_allowed) {
		while (JString::strpos($mMessage, '{?php') != false) {
			$charCount = JString::strpos($mMessage, '{?php');

			$myRelativeCount = JString::strpos($mMessage, '?}', $charCount);

			if ($myRelativeCount !== false) {
				$myPiece = JString::substr($mMessage, $charCount, ($myRelativeCount-$charCount));
				$myPHP = JString::substr($myPiece, 5, ($myRelativeCount-$charCount)-5);

				ob_start();
				eval($myPHP);
				$contents = ob_get_contents();
				ob_end_clean();

				$mMessage = str_replace('{?php'. $myPHP .'?}', $contents, $mMessage);
			}
		}
  }

  // links and images fix
  $mMessage = preg_replace('#src[ ]*=[ ]*\"(?!https?://)(?:\.\./|\./|/)?#',  'src="'.$mybase,  $mMessage);
  $mMessage = preg_replace('#href[ ]*=[ ]*\"(?!https?://|mailto:|\#)(?:\.\./|\./|/)?#', 'href="'.$mybase, $mMessage);

  return $mMessage;

}

function FilterNewsletterFTF($mySubEmail, $ftf_pre_text, $fromSubMail, $nid, $mMessage) {

  // initialize links
  $mybase = str_replace('/administrator/', '/', JURI::base());

  $mySubLink = '<a href="' . $mybase . 'index.php?option=com_nspro">' . $mybase . 'index.php?option=com_nspro</a>';

  $ftf_pre_text = str_replace('%e', $fromSubMail, $ftf_pre_text);
  $ftf_pre_text = str_replace('%s', $mybase, $ftf_pre_text);
  $ftf_pre_text = str_replace('%l', $mySubLink, $ftf_pre_text);

  $ftf_pre_text = str_replace('&lt;', '<', $ftf_pre_text);
  $ftf_pre_text = str_replace('&gt;', '>', $ftf_pre_text);

  $mMessage = str_replace('{link:UNSUB}', '('.JText::_('Original Message') . ': "', $mMessage);
  $mMessage = str_replace('{link:EDITLISTS}', '('.JText::_('Original Message') . ': "', $mMessage);
  $mMessage = str_replace('{/link}', '")', $mMessage);

  $mMessage = $ftf_pre_text . $mMessage;

  $mMessage = FilterNewsletterSmartText(JText::_('Friend'), $mySubEmail, $nid, $mMessage, 0);

  return $mMessage;

}

function GetSubRowsByMailingLists($emails_per_send, $mailing_lists, $confirmed = 1, $LastID = 0, $orderby = 'id') {
  $db =& JFactory::getDBO();

  // general query
  $query = 'SELECT * FROM `#__nspro_subs` WHERE `confirmed` = "' . mysql_escape_string($confirmed) . '"';
  // last id
  if ($LastID > 0) {
    $query = $query . ' AND `id` > ' . $LastID;
  }
  // mailing lists

  $newslists = array();
  if ($mailing_lists !== '') {
    $newslists = explode(',', $mailing_lists);
  }

  if (count($newslists) > 0) {
    $query = $query . ' AND (';
    $firstpass = true;
    foreach ($newslists as $newslist) {
      if ($firstpass) {
        $query = $query . '(FIND_IN_SET("'.$newslist.'", `mailing_lists`) > 0)';
        $firstpass = false;
      }
      else {
        $query = $query . 'OR (FIND_IN_SET("'.$newslist.'", `mailing_lists`) > 0)';
      }
    }
    $query = $query . ')';
  }

  $query = $query . ' ORDER BY `' . $orderby . '`';
  if ($emails_per_send != 0) {
    $query .= ' LIMIT 0, '.$emails_per_send;
  }
  $db->setQuery($query);
  $subscribers = $db->loadRowList();

  return $subscribers;
}

function GetSubCountByMailingLists($mailing_lists, $confirmed = 1, $LastID = 0, $orderby = 'id') {
  $db =& JFactory::getDBO();

  // general query
  $query = 'SELECT COUNT(`id`) FROM `#__nspro_subs` WHERE `confirmed` = "' . mysql_escape_string($confirmed) . '"';
  // last id
  if ($LastID > 0) {
    $query = $query . ' AND `id` > ' . $LastID;
  }
  // mailing lists

  $newslists = array();
  if ($mailing_lists !== '') {
    $newslists = explode(',', $mailing_lists);
  }

  if (count($newslists) > 0) {
    $query = $query . ' AND (';
    $firstpass = true;
    foreach ($newslists as $newslist) {
      if ($firstpass) {
        $query = $query . '(FIND_IN_SET("'.$newslist.'", `mailing_lists`) > 0)';
        $firstpass = false;
      }
      else {
        $query = $query . 'OR (FIND_IN_SET("'.$newslist.'", `mailing_lists`) > 0)';
      }
    }
    $query = $query . ')';
  }

  $query = $query . ' ORDER BY `' . $orderby . '`';
  $db->setQuery($query);
  $scount = $db->loadResult();

  return $scount;
}

function GetAttachmentsByNewsletterId($nid) {
  $target_dir = JPATH_ADMINISTRATOR.DS."components/com_nspro/uploads/";

  $db =& JFactory::getDBO();
  $query = 'SELECT * FROM `#__nspro_newsletter_attachments` WHERE `newsletter_id` = "' . mysql_escape_string($nid) . '" ORDER BY `id`';
  $db->setQuery($query);
  $mattachments = $db->loadObjectList();

  $attachment = array();
  if (count($mattachments) > 0) {
    foreach( $mattachments as $mat) {
      $attachment[] = $target_dir.$mat->filename;
    }
  }

  return $attachment;
}

// This is a copy of the JUtility::sendMail
// because that one will be deprecated in the future.
//
// string  $from: From e-mail address
// string  $fromname: From name
// mixed   $recipient: Recipient e-mail address(es)
// string  $subject: E-mail subject
// string  $body: Message body
// boolean $mode: false = plain text, true = HTML
// mixed   $cc: CC e-mail address(es)
// mixed   $bcc: BCC e-mail address(es)
// mixed   $attachment: Attachment file name(s)
// mixed   $replyto: Reply to email address(es)
// mixed   $replytoname: Reply to name(s))
// @return boolean True on success
//
function MySendMail($from, $fromname, $recipient, $subject, $body,
                    $mode=0, $cc=null, $bcc=null, $attachment=null,
                    $replyto=null, $replytoname=null) {

// Get a JMail instance
  $mail =& JFactory::getMailer();

  $mail->setSender(array($from, $fromname));
  $mail->setSubject($subject);
  $mail->setBody($body);

// Are we sending the email as HTML?
  if ( $mode ) {
    $mail->IsHTML(true);
  }

  $mail->addRecipient($recipient);
  $mail->addCC($cc);
  $mail->addBCC($bcc);
  $mail->addAttachment($attachment);

// Take care of reply email addresses
  if( is_array( $replyto ) ) {
    $numReplyTo = count($replyto);
    for ( $i=0; $i < $numReplyTo; $i++){
      $mail->addReplyTo( array($replyto[$i], $replytoname[$i]) );
    }
  }
  elseif( isset( $replyto ) ) {
    $mail->addReplyTo( array( $replyto, $replytoname ) );
  }

  return $mail->Send();
}

// This is a custom version of the JUtility::sendMail
// to be able to include a Bounce Header
function MySendMailBounceHeader($from, $fromname, $recipient, $subject, $body,
                                $mode=0, $cc=null, $bcc=null, $attachment=null,
                                $replyto=null, $replytoname=null)  {

// Get a JMail instance
  $mail =& JFactory::getMailer();

  $mail->setSender(array($from, $fromname));

  $jversion = new JVersion();
  $j15 = ($jversion->RELEASE == '1.5');
	if ($j15 != true) {
		jimport( 'joomla.html.parameter' );
	}

  jimport('joomla.application.component.helper');
  $params = JComponentHelper::getParams( 'com_nspro' );  
  if ($j15 == true) {
    $component = JComponentHelper::getComponent( 'com_nspro' );
    $params = new JParameter( $component->params );
  }

  if ($j15 == true) {
    $bounce_address = $params->get('bounce_address', 'bounce@yoursite.com');
  }
  else {
    $bounce_address = $params->getValue('data.params.bounce_address', 'bounce@yoursite.com');
  }
    
  if ($bounce_address != 'bounce@yoursite.com') {
    $mheader = "Return-path: <{$bounce_address}>\r\n";
    $mheader .= "Errors-To: <$bounce_address>\r\n";
    $mheader .= "NSPro-SendingTo: <$recipient>\r\n";
    $mail->AddCustomHeader($mheader);
    $mail->Sender = $bounce_address;
  }

  $mail->setSubject($subject);

  $mail->setBody($body);

// Are we sending the email as HTML?
  if ( $mode ) {
    $mail->IsHTML(true);
  }

  $mail->addRecipient($recipient);
  $mail->addCC($cc);
  $mail->addBCC($bcc);
  $mail->addAttachment($attachment);

// Take care of reply email addresses
  if( is_array( $replyto ) ) {
    $numReplyTo = count($replyto);
    for ( $i=0; $i < $numReplyTo; $i++){
      $mail->addReplyTo( array($replyto[$i], $replytoname[$i]) );
    }
  }
  elseif( isset( $replyto ) ) {
    $mail->addReplyTo( array( $replyto, $replytoname ) );
  }

  return $mail->Send();
}

function ConnectToBounceAddress($params) {
  
  set_time_limit(120);
  ignore_user_abort(true);
  
  $jversion = new JVersion();
  $j15 = ($jversion->RELEASE == '1.5');
  
  if ($j15 == true) {
    $bounce_address = $params->get('bounce_address', 'bounce@yoursite.com');
    $bounce_mailserver = $params->get('bounce_mailserver', '');
    $bounce_port = $params->get('bounce_port', '');
    $bounce_protocol = $params->get('bounce_protocol', '0'); // IMAP, POP3, NNTP
    $bounce_security = $params->get('bounce_security', '0'); // None, SSL, TLS
    $bounce_selfsign = $params->get('bounce_selfsign', '0');
    $bounce_username = $params->get('bounce_username', '');
    $bounce_password = $params->get('bounce_password', '');
    
    $bounce_action = $params->get('bounce_action', '1'); // No action, Set Unconfirmed or Delete
    $bounce_notify = $params->get('bounce_notify', '0'); // notify or not
    $bounce_max = $params->get('bounce_max', '1000');
    $bounce_notification_address = $params->get('unsub_mail_recipient', 'email@email.com');
    $unsub_from_name = $params->get('unsub_from_name', 'Newsletter Subscriber');
    $unsub_from_email = $params->get('unsub_from_email', 'newsletter_subscriber@yoursite.com');
  }
  else {
    $bounce_address = $params->getValue('data.params.bounce_address', 'bounce@yoursite.com');
    $bounce_mailserver = $params->getValue('data.params.bounce_mailserver', '');
    $bounce_port = $params->getValue('data.params.bounce_port', '');
    $bounce_protocol = $params->getValue('data.params.bounce_protocol', '0'); // IMAP, POP3, NNTP
    $bounce_security = $params->getValue('data.params.bounce_security', '0'); // None, SSL, TLS
    $bounce_selfsign = $params->getValue('data.params.bounce_selfsign', '0');
    $bounce_username = $params->getValue('data.params.bounce_username', '');
    $bounce_password = $params->getValue('data.params.bounce_password', '');
    
    $bounce_action = $params->getValue('data.params.bounce_action', '1'); // No action, Set Unconfirmed or Delete
    $bounce_notify = $params->getValue('data.params.bounce_notify', '0'); // notify or not
    $bounce_max = $params->getValue('data.params.bounce_max', '1000');
    $bounce_notification_address = $params->getValue('data.params.unsub_mail_recipient', 'email@email.com');
    $unsub_from_name = $params->getValue('data.params.unsub_from_name', 'Newsletter Subscriber');
    $unsub_from_email = $params->getValue('data.params.unsub_from_email', 'newsletter_subscriber@yoursite.com');
  }
  
  // Check the parameters.
  if ($bounce_mailserver == '') {
    $str = JText::_('Error: Please configure the Mail Server in the Bounce Check Parameters, which are found in the Component Parameters.');
    return($str);
  }
  if ($bounce_port == '') {
    $str = JText::_('Error: Please configure the Port in the Bounce Check Parameters, which are found in the Component Parameters.');
    return($str);
  }
  if ($bounce_username == '') {
    $str = JText::_('Error: Please configure the Bounce Account Username in the Bounce Check Parameters, which are found in the Component Parameters.');
    return($str);
  }
  if ($bounce_password == '') {
    $str = JText::_('Error: Please configure the Bounce Account Password in the Bounce Check Parameters, which are found in the Component Parameters.');
    return($str);
  }
  
  //global $mainframe;
  $mainframe = JFactory::getApplication();  

  if ($unsub_from_name == 'Newsletter Subscriber') {
    $unsub_from_name = $mainframe->getCfg('fromname');
  }
  if ($unsub_from_email == 'newsletter_subscriber@yoursite.com') {
    $unsub_from_email = $mainframe->getCfg('mailfrom');
  }

  $bounce_prtc = '';
  switch ($bounce_protocol) {
    case 0:
      $bounce_prtc = '/imap';
      break;
    case 1:
      $bounce_prtc = '/pop3';
      break;
    case 2:
      $bounce_prtc = '/nntp';
      break;
  }
  $bounce_sec = '';
  switch ($bounce_security) {
    case 0:
      $bounce_sec = '/notls';
      break;
    case 1:
      $bounce_sec = '/ssl';
      break;
    case 2:
      $bounce_sec = '/tls';
      break;
  }

  $bounce_sign = '';
  if ($bounce_selfsign == '1') {
    $bounce_sign = '/novalidate-cert';
  }

  $connection_str = '{' . $bounce_mailserver . ':' . $bounce_port . $bounce_prtc . $bounce_sec . $bounce_sign . '}INBOX';

  $mbox = imap_open($connection_str, $bounce_username, $bounce_password);
  if ($mbox !== false) {
    $str = processBounces($mbox, $bounce_max, $bounce_action, $bounce_notify, $bounce_notification_address, $unsub_from_email, $unsub_from_name);
    return($str);
  }
  else {
    $str = JText::_('Error: Could not connect. Please check the Bounce Check parameters with your host.');
    return($str);
  }
}

function processBounces($mbox, $max = 1000, $bounce_action, $bounce_notify,
                        $bounce_notification_address, $unsub_from_email, $unsub_from_name) {
  $num = imap_num_msg($mbox);

  if ($max > 0) {
    if ($num > $max) {
      $num = $max;
    }
  }

  $bounce_count = 0;
  $action_count = 0;
  $addresses = array();
  for ($i=1; $i <= $num; $i++) {
    $eaddress = '';
    $isBounce = processBounce($mbox, $i, $bounce_action, $eaddress);
    switch($isBounce) {
      case '0': // no bounce
        break;
      case '1': // bounced, email not found
        $bounce_count = $bounce_count + 1;
        break;
      case '2': // bounced, action completed
        $bounce_count = $bounce_count + 1;
        $action_count = $action_count + 1;
        $addresses[] = $eaddress;
        break;
    }
  }

  $str = JText::_('Found:') . ' ' . $bounce_count . ' ' . JText::_('bounce(s).') . ' ';
  $str = $str . JText::_('Processed:') . ' ' . $action_count . ' ' . JText::_('subscriber(s).');

  if ($bounce_count > 0) {
    imap_expunge($mbox); // to delete the messages
  }

  if (($bounce_count > 0) && ($bounce_notify)) {
    // send mail to $bounce_notification_address
    $subject = JText::_('NS Pro Notification: Bounces Found in your List.');
    $body = $str . "<br/>";
    if (count($addresses) > 0) {
      $body .= JText::_('The following email addresses bounced:') . "<br/>";
      foreach($addresses as $adr) {
        $body .= $adr . "<br/>";
      }
    }
    MySendMail($unsub_from_email, $unsub_from_name, $bounce_notification_address, $subject, $body, true);
  }

  imap_close($mbox, CL_EXPUNGE);

  return($str);
}

function processBounce($mbox, $i, $bounce_action, &$eaddress) {
  $rgxp = "/NSPro-SendingTo: <.*>/i";
  $body = imap_body($mbox,$i);
  $matches = array();
  if (preg_match($rgxp, $body, $matches)) {
    $mymatch = $matches[0];
    $mymatch = str_replace('NSPro-SendingTo: <', '', $mymatch);
    $subemail = mysql_escape_string(str_replace('>', '', $mymatch));

    $db =& JFactory::getDBO();
    $query = 'SELECT COUNT(*) FROM `#__nspro_subs` WHERE `email` = "' . $subemail . '"';
    $db->setQuery($query);
    $mySub = $db->loadResult();

    $returnValue = '1';
    if ($mySub > 0) {
      $query = '';
      if ($bounce_action == '1') {
        $query = 'UPDATE `#__nspro_subs` SET `confirmed` = "0" WHERE `email` = "' . $subemail . '"';
      }
      else if ($bounce_action == '2') {
        $query = 'DELETE FROM `#__nspro_subs` WHERE `email` = "' . $subemail . '"';
      }
      else if ($bounce_action == '3') {
        $db->setQuery('DELETE FROM `#__users` WHERE `email` = "' . $subemail . '"');
        $db->query();
        $query = 'DELETE FROM `#__nspro_subs` WHERE `email` = "' . $subemail . '"';
      }
      $db->setQuery($query);
      if (!$db->query()) {
        // subscriber wasn't processed
      }
      else {
        $eaddress = $subemail;
        $returnValue = '2';
      }
    }
    imap_delete($mbox, $i);
    return($returnValue);
  }
  else {
    return('0');
  }
}


// FIELD FUNCTIONS

// Parameter 1 is 'site' or 'admin'
function FilterInitialValue($end, $val) {
  jimport('joomla.application.component.helper');
  $params = JComponentHelper::getParams( 'com_nspro' );
  $jversion = new JVersion();
  $j15 = ($jversion->RELEASE == '1.5');
  if ($j15 == true) {
    $component = JComponentHelper::getComponent( 'com_nspro' );
    $params = new JParameter( $component->params );
  }
  
  if ($j15 == true) {
    $dofilter = $params->get('initial_value_fiter_admin', '1');
  }
  else {
    $dofilter = $params->getValue('data.params.initial_value_fiter_admin', '1');
  }
  if (!$dofilter) {
    if ($end == 'admin') {
      $val = '';
      return $val;
    }
  }
  if ($val == '#subscriber_ip#') {
    $val = $_SERVER['REMOTE_ADDR'];
  }
  else if ($val == '#page_url#') {
    $val = (!empty($_SERVER['HTTPS'])) ? "https://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] : "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
  }
  else if ($val == '#web_browser#') {
    $val = getBrowser();
  }
  else if ($val == '#operating_system#') {
    $val = getOS();
  }
  return $val;
}

function GetFieldInputModulePlugin($afield, $avalue = '', $class_sfx = '', $source = 'plugin', $size = '20', $rows = '3', $cols = '25', $swidth = '135') {
  $result = '';

  $mainclass = (($source == 'plugin') ? "nspro " : "modnspro ");
  $name_prefix = (($source == 'plugin') ? "nsp_" : "mp_");

  switch($afield->fieldtype) {
    case '0':
      $result = '<input class="'.$mainclass.'inputbox'.$class_sfx.'" type="text" size="'.$size.'" id="'.$name_prefix.'field' . $afield->id . '" name="'.$name_prefix.'field' . $afield->id . '"';
      if (($avalue == '') && ($afield->value != '')) {
        $myval = FilterInitialValue($admin, $afield->value);
        $result = $result . ' value="'.$myval.'"/>';
      }
      else if ($avalue != '') {
        $result = $result . ' value="'.$avalue.'"/>';
      }
      else {
        $result = $result . '/>';
      }
      break;
    case '1':
      $result = '<textarea class="'.$mainclass.'textarea'.$class_sfx.'" rows="'.$rows.'" cols="'.$cols.'" id="'.$name_prefix.'field' . $afield->id . '" name="'.$name_prefix.'field' . $afield->id . '">';
      if (($avalue == '') && ($afield->value != '')) {
        $result = $result . $afield->value;
      }
      else if ($avalue != '') {
        $result = $result . $avalue;
      }
      $result .= '</textarea>';
      break;
    case '2':
      $thevalue = false;
      if (($avalue == '') && ($afield->value != '')) {
        $thevalue = (boolean) $afield->value;
      }
      else if ($avalue != '') {
        $thevalue = (boolean) $avalue;
      }
      $fname = $name_prefix.'field' . $afield->id;
      $result = JHTML::_( 'select.booleanlist',  $fname, 'class="'.$mainclass.'inputbox'.$class_sfx.'"', $thevalue);
      break;
    case '3':
      $fname = 'field' . $afield->id;
      $options = explode(',', $afield->value);
      $result = '';
      $i = 1;
      foreach($options as $opt) {
        $result .= '<input class="'.$mainclass.'inputbox radiobutton'.$class_sfx.'" type="radio" name="'.$name_prefix.$fname.'" value="'.$opt.'"';
        if ((!($avalue == '')) && ($opt == $avalue)) {
          $result .= ' checked="checked"';
        }
        $result .= '/> ' . JText::_($opt);
        if (($i % 2) == 0) {
          $result .= '<br/>';
        }
        $i++;
      }
      break;
    case '4':
      $fname = 'field' . $afield->id;
      $options = explode(',', $afield->value);
      $avalues = explode(',', $avalue);
      $result = '';
      $i = 1;
      foreach($options as $opt) {
        $result .= '<input class="'.$mainclass.'inputbox checkbox'.$class_sfx.'" type="checkbox" name="'.$name_prefix.$fname.'[]" value="'.$opt.'"';
        foreach($avalues as $av) {
          if ((!($avalue == '')) && ($opt == $av)) {
            $result .= ' checked="checked"';
          }
        }
        $result .= '/> ' . JText::_($opt);
        if (($i % 2) == 0) {
          $result .= '<br/>';
        }
        $i++;
      }
      break;
    case '5':
      $fname = 'field' . $afield->id;
      $options = explode(',', $afield->value);
      $result = '<select name="'.$name_prefix.$fname.'" id="'.$name_prefix.$fname.'" style="width: '.$swidth.'px;" class="'.$mainclass.'inputbox'.$class_sfx.'">';
      foreach($options as $opt) {
        $result .= '<option value="'.$opt.'"';
        if ((!($avalue == '')) && ($opt == $avalue)) {
          $result .= ' selected="selected"';
        }
        $result .='>'.JText::_($opt).'</option>';
      }
      $result .= '</select>';
      break;
    case '6':
      $fname = 'field' . $afield->id;
      $options = explode(',', $afield->value);
      $avalues = explode(',', $avalue);
      $result = '<select name="'.$name_prefix.$fname.'[]" id="'.$name_prefix.$fname.'" style="width: '.$swidth.'px;" class="'.$mainclass.'inputbox'.$class_sfx.'" multiple="multiple">';
      foreach($options as $opt) {
        $result .= '<option value="'.$opt.'"';
        foreach($avalues as $av) {
          if ((!($avalue == '')) && ($opt == $av)) {
            $result .= ' selected="selected"';
          }
        }
        $result .= '>'.JText::_($opt).'</option>';
      }
      $result .= '</select>';
      break;
    case '7':
      $result = '<input class="'.$mainclass.'inputbox'.$class_sfx.'" type="hidden" id="'.$name_prefix.'field' . $afield->id . '" name="'.$name_prefix.'field' . $afield->id . '"';
      if (($avalue == '') && ($afield->value != '')) {
        $myval = FilterInitialValue($admin, $afield->value);
        $result = $result . ' value="'.$myval.'"/>';
      }
      else if ($avalue != '') {
        $result = $result . ' value="'.$avalue.'"/>';
      }
      else {
        $result = $result . '/>';
      }
      break;
  }

  return $result;
}

function GetFieldInputSubForm($afield, $isNew = false, $avalue = '', $admin = 'admin') {
  $result = '';

  switch($afield->fieldtype) {
    case '0';
    case '7';
      $result = '<input class="inputbox" type="text" size="60" id="field' . $afield->id . '" name="field' . $afield->id . '"';
      if (($isNew) && ($afield->value != '')) {
        $myval = FilterInitialValue($admin, $afield->value);
        $result = $result . ' value="'.$myval.'"/>';
      }
      else if ($avalue != '') {
        $result = $result . ' value="'.$avalue.'"/>';
      }
      else {
        $result = $result . '/>';
      }
      break;
    case '1':
      $result = '<textarea class="textarea" rows="6" cols="35" id="field' . $afield->id . '" name="field' . $afield->id . '">';
      if (($isNew) && ($afield->value != '')) {
        $result = $result . $afield->value;
      }
      else if ($avalue != '') {
        $result = $result . $avalue;
      }
      $result .= '</textarea>';
      break;
    case '2':
      $thevalue = false;
      if (($isNew) && ($afield->value != '')) {
        $thevalue = (boolean) $afield->value;
      }
      else if ($avalue != '') {
        $thevalue = (boolean) $avalue;
      }
      $fname = 'field' . $afield->id;
      $result = JHTML::_( 'select.booleanlist',  $fname, 'class="inputbox"', $thevalue);
      break;
    case '3':
      $fname = 'field' . $afield->id;
      $options = explode(',', $afield->value);
      $result = '';
      $i = 1;
      foreach($options as $opt) {
        $result .= '<input class="inputbox radiobutton" type="radio" name="'.$fname.'" value="'.$opt.'"';
        if ((!$isNew) && ($opt == $avalue)) {
          $result .= ' checked="checked"';
        }
        $result .= '/> ' . JText::_($opt);
        if (($i % 3) == 0) {
          $result .= '<br/>';
        }
        $i++;
      }
      break;
    case '4':
      $fname = 'field' . $afield->id;
      $options = explode(',', $afield->value);
      $avalues = explode(',', $avalue);
      $result = '';
      $i = 1;
      foreach($options as $opt) {
        $result .= '<input class="inputbox checkbox" type="checkbox" name="'.$fname.'[]" value="'.$opt.'"';
        foreach($avalues as $av) {
          if ((!$isNew) && ($opt == $av)) {
            $result .= ' checked="checked"';
          }
        }
        $result .= '/> ' . JText::_($opt);
        if (($i % 3) == 0) {
          $result .= '<br/>';
        }
        $i++;
      }
      break;
    case '5':
      $fname = 'field' . $afield->id;
      $options = explode(',', $afield->value);
      $result = '<select name="'.$fname.'" id="'.$fname.'" style="width: 270px;" class="inputbox">';
      foreach($options as $opt) {
        $result .= '<option value="'.$opt.'"';
        if ((!$isNew) && ($opt == $avalue)) {
          $result .= ' selected="selected"';
        }
        $result .='>'.JText::_($opt).'</option>';
      }
      $result .= '</select>';
      break;
    case '6':
      $fname = 'field' . $afield->id;
      $options = explode(',', $afield->value);
      $avalues = explode(',', $avalue);
      $result = '<select name="'.$fname.'[]" id="'.$fname.'" style="width: 270px;" class="inputbox" multiple="multiple">';
      foreach($options as $opt) {
        $result .= '<option value="'.$opt.'"';
        foreach($avalues as $av) {
          if ((!$isNew) && ($opt == $av)) {
            $result .= ' selected="selected"';
          }
        }
        $result .= '>'.JText::_($opt).'</option>';
      }
      $result .= '</select>';
      break;
  }

  return $result;
}

function GetRegexp($reg) {

  // Validation Regular Expressions
  //Email Address
  $email_regexp = '/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/';

  //Address: State code (US)
  $us_state_code_regexp = '/\\b(?:A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])\\b/';

  //Address: ZIP code (US)
  $us_zip_code_regexp = '/\\b[0-9]{5}(?:-[0-9]{4})?\\b/';

  //Postal code (Canada)
  $canada_postal_code_regexp = '/\\b[ABCEGHJKLMNPRSTVXY][0-9][A-Z] [0-9][A-Z][0-9]\\b/';

  //Postal code (UK)
  $uk_postal_code = '/\\b[A-Z]{1,2}[0-9][A-Z0-9]? [0-9][ABD-HJLNP-UW-Z]{2}\\b/';

  //IP address
  //Matches 0.0.0.0 through 255.255.255.255
  //Use this regex to match IP numbers with accurracy, without access to the individual IP numbers.
  $ip_regexp = '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b/';

  //Phone Number (North America)
  //Matches 3334445555, 333.444.5555, 333-444-5555, 333 444 5555, (333) 444 5555 and all combinations thereof.
  $phone_north_america_regexp = '/\\(?[0-9]{3}\)?[-. ]?[0-9]{3}[-. ]?[0-9]{4}/';

  $resreg = $reg;
  if ($reg == '#email#') {
    $resreg = $email_regexp;
  }
  else if ($reg == '#us_state_code#') {
    $resreg = $us_state_code_regexp;
  }
  else if ($reg == '#us_zip_code#') {
    $resreg = $us_zip_code_regexp;
  }
  else if ($reg == '#canada_postal_code#') {
    $resreg = $canada_postal_code_regexp;
  }
  else if ($reg == '#uk_postal_code#') {
    $resreg = $uk_postal_code;
  }
  else if ($reg == '#north_america_phone#') {
    $resreg = $phone_north_america_regexp;
  }
  else if ($reg == '#ip_address#') {
    $resreg = $ip_regexp;
  }
  return $resreg;
}

function FieldHadError($resultstring, $fieldname) {
  if (JString::strpos($resultstring, JText::_($fieldname)) === false) {
    return false;
  }
  return true;
}

function ValidateExtraFields($data, $published = false, $br = '<br/>', $errorcolor = '', $source = '') {
  $db =& JFactory::getDBO();

  $name_prefix = '';
  if ($source != '') {
    $name_prefix = (($source == 'plugin') ? "nsp_" : "mp_");
  }

  $query = 'SELECT * FROM `#__nspro_fields`';
  if ($published) {
    $query .= ' WHERE `published` = true';
  }
  $db->setQuery($query);
  $fields = $db->loadObjectList();

  $result = '';

  $osp = '';
  $csp = '';
  if ($errorcolor != '') {
    $osp = '<span style="color: '.$errorcolor.'">';
    $csp = '</span>';
  }

  foreach($fields as $field) {
    if (($field->required) && ( (!isset($data[$name_prefix.'field'.$field->id])) || ($data[$name_prefix.'field'.$field->id] == '')) ) {
      $rstring = str_replace('%s', JText::_($field->name), JText::_('Field %s is required'));
      $result .= $osp . $rstring . "\n" . $csp . $br;
    }
    else if (isset($data[$name_prefix.'field'.$field->id])) {
      $fvalue = $data[$name_prefix.'field'.$field->id];

      // validate field
      if ($field->regexp != '') {
        $realregexp = GetRegexp($field->regexp);
        if (!preg_match($realregexp, $fvalue)) {
          $rstring = str_replace('%s', JText::_($field->name), JText::_('Answer for Field %s was not valid'));
          $result .= $osp . $rstring . "\n" . $csp . $br;
        }
      }
    }
  }
  if ($result == '') {
    return true;
  }
  else {
    return $result;
  }
}

function FieldValueExists($subid, $fieldid) {
  $db =& JFactory::getDBO();
  $query = 'SELECT COUNT(*) FROM `#__nspro_field_values` WHERE `subscriber_id` = "'.mysql_escape_string($subid).'" AND `field_id` = "'.mysql_escape_string($fieldid).'"';
  $db->setQuery($query);
  $count = $db->loadResult();
  return ($count > 0);
}

function ExtraFieldsToString($source, $subid) {
  $result = '';
  $db =& JFactory::getDBO();
  
  $name_prefix = '';
  if ($source != 'confirm') {
    $name_prefix = (($source == 'plugin') ? "nsp_" : "mp_");
  }
  
  $query = 'SELECT * FROM `#__nspro_fields` WHERE `published` = true';
  $db->setQuery($query);
  $fields = $db->loadObjectList();  

  if ($source == 'confirm') {
		foreach($fields as $field) {
			if (FieldValueExists($subid, $field->id)) {
        $query = 'SELECT `value` FROM `#__nspro_field_values` WHERE `subscriber_id` = "'.mysql_escape_string($subid).'" AND `field_id` = "'.mysql_escape_string($field->id).'"';
        $db->setQuery($query);
        $myvalue = $db->loadResult();
        
        $result .= JText::_($field->name) . ': ' . $myvalue . "\n";
			}
	  }
  }
  else {
		foreach($fields as $field) {
			if (isset($_POST[$name_prefix.'field'.$field->id])) {
				$fvalue = $_POST[$name_prefix.'field'.$field->id];
				if (($field->fieldtype == '4') || ($field->fieldtype == '6')) {
					$fvalue = implode(',', $fvalue);
				}

        $result .= JText::_($field->name) . ': ' . $fvalue . "\n";
			}
		}
  }
  
  return $result;
}

function SaveExtraFields($subid, $data, $published = false, $source = '') {
  $db =& JFactory::getDBO();

  $name_prefix = '';
  if ($source != '') {
    $name_prefix = (($source == 'plugin') ? "nsp_" : "mp_");
  }

  $query = 'SELECT * FROM `#__nspro_fields`';
  if ($published) {
    $query .= ' WHERE `published` = true';
  }

  $db->setQuery($query);
  $fields = $db->loadObjectList();

  foreach($fields as $field) {
    if (isset($data[$name_prefix.'field'.$field->id])) {
      $fvalue = $data[$name_prefix.'field'.$field->id];
      if (($field->fieldtype == '4') || ($field->fieldtype == '6')) {
        $fvalue = implode(',', $fvalue);
      }

      if (FieldValueExists($subid, $field->id)) {
        $query = 'UPDATE `#__nspro_field_values` SET `value` = "' . mysql_escape_string($fvalue) .
        '" WHERE `subscriber_id` = "'.mysql_escape_string($subid).'" AND `field_id` = "'.mysql_escape_string($field->id).'"';
      }
      else {
        $query = 'INSERT INTO `#__nspro_field_values` (`subscriber_id`, `field_id`, `value`) VALUES("'.mysql_escape_string($subid).'", "'.mysql_escape_string($field->id).'", "'.
        mysql_escape_string($fvalue).'")';
      }
      $db->setQuery($query);
      if (!$db->query()) {
        return JText::_('Field Query Failed:') . ' ' . JText::_($field->name);
      }
    }
  }

  return true;


}

// These functions are from JoomlaWatch.
// Thank you JoomlaWatch!
function getOS() {
  $userAgent = strip_tags(@ $_SERVER['HTTP_USER_AGENT']);

  if (stristr($userAgent, "Mac"))
    $os = "Mac";
  else if (stristr($userAgent, "Linux"))
    $os = "Linux";
  else if (stristr($userAgent, "Windows 95"))
    $os = "Windows 98";
  else if (stristr($userAgent, "Windows 98"))
    $os = "Windows 98";
  else if (stristr($userAgent, "Windows ME"))
    $os = "Windows 98";
  else if (stristr($userAgent, "Windows NT 4.0"))
    $os = "Windows NT";
  else if (stristr($userAgent, "Windows NT 5.1"))
    $os = "Windows XP";
  else if (stristr($userAgent, "Windows NT 6.0"))
    $os = "Windows Vista";
  else if (stristr($userAgent, "Windows NT 6.1"))
    $os = "Windows 7";
  else if (stristr($userAgent, "Windows"))
    $os = "Windows";

  return @ $os;
}

function getBrowser() {
  $userAgent = strip_tags(@ $_SERVER['HTTP_USER_AGENT']);

  if (stristr($userAgent, "Chrome"))
    $browser = "Chrome";
  else if (stristr($userAgent, "Safari"))
    $browser = "Safari";
  else if (stristr($userAgent, "MSIE"))
    $browser = "Explorer";
  else if (stristr($userAgent, "Firefox"))
    $browser = "Firefox";
  else if (stristr($userAgent, "Opera"))
    $browser = "Opera";
  else if (stristr($userAgent, "Mozilla"))
    $browser = "Mozilla";

  return @ $browser;
}

function schedulesend($bounceresult) {
	$target_dir = JPATH_ADMINISTRATOR.DS."components/com_nspro/uploads/";

	jimport('joomla.application.component.helper');
	$params = JComponentHelper::getParams( 'com_nspro' );
	
	$jversion = new JVersion();
  $j15 = ($jversion->RELEASE == '1.5');
  if ($j15 == true) {
	  $component = JComponentHelper::getComponent( 'com_nspro' );
	  $params = new JParameter( $component->params );
	}
  
  if ($j15 == true) {
	  $newsletter_delay = $params->get( 'newsletter_delay', '' );
	  $maxtime_limit = $params->get('maxtime_limit', '300');
	}
	else {
	  $newsletter_delay = $params->getValue( 'data.params.newsletter_delay', '' );
	  $maxtime_limit = $params->getValue('data.params.maxtime_limit', '300');
	}

	$db =& JFactory::getDBO();
	$query = 'SELECT COUNT(*) FROM `#__nspro_subs` WHERE `confirmed` = true';
	$db->setQuery($query);
	$mcount = $db->loadResult();

  // find all newsletters that are scheduled before the current time.
  $query = 'SELECT * FROM `#__nspro_newsletters` WHERE `is_scheduled` = true AND `scheduledatetime` <= NOW()';
  $db->setQuery($query);
  
  $newsletters = $db->loadObjectList();

	if ($newsletter_delay != '') {
		$mtlim = $newsletter_delay * count($newsletters) * $mcount + 20;
		if ($mtlim < $maxtime_limit) {
			set_time_limit($mtlim);
		}
		else {
			set_time_limit($maxtime_limit);
		}
	}
	else {
		set_time_limit(0);
	}
  
	ignore_user_abort(true);
	ob_start();
	print '<html><head><title>NS Pro Cron Job Results</title></head><body>'.
	      'Bounce Check Result: ' . $bounceresult . "\n<br/>" .
        'Newsletters To Send: ' . count($newsletters) . "\n<br/>" . 
        'Current Date and Time: ' . date('r') . 
        '</body></html>';

	$msize = ob_get_length();
	header("Content-Length: $msize");
	header('Connection: close');
	ob_end_flush();
	ob_flush();
	flush();

  if (count($newsletters) > 0) {
    $errors = 0;
    $error_report = '';
    foreach($newsletters as $mnewsletter) {
      $emails_per_send = $mnewsletter->emails_per_send;
      $mcount = GetSubCountByMailingLists($mnewsletter->mailing_lists, 1, $mnewsletter->LastID, 'id');
      $msubs = GetSubRowsByMailingLists($emails_per_send, $mnewsletter->mailing_lists, 1, $mnewsletter->LastID, 'id');
      
      $applySent = false;
      if ( ($emails_per_send == 0) || ($mcount <= $emails_per_send) ) {
        $n = count($msubs);
        $applySent = true;
      }
      else {
        $n = $emails_per_send;
      }

      for ($i=0; $i < $n; $i++) {
        $msub = $msubs[$i];
        $mMessage = FilterNewsletterSmartText($msub[1], $msub[2], $mnewsletter->id, $mnewsletter->message, $msub[0]);

        $attachment = GetAttachmentsByNewsletterId($mnewsletter->id);

        if (MySendMailBounceHeader($mnewsletter->fEmail, $mnewsletter->fName, $msub[2], $mnewsletter->subject, $mMessage, true, null, null, $attachment) !== true) {
          $errors = $errors + 1;
          $error_report = JText::_('Error sending Newsletter ID:') . ' ' . $mnewsletter->id . ', ' . JText::_('Subscriber Email:') . ' ' . $msub[2] . ', '. JText::_('Date & Time:') . ' ' . date('r') . "\n";
          break;
        }
        else {
          $query = 'UPDATE `#__nspro_newsletters` SET `LastID` = "'.$msub[0].'" WHERE `id` = "'.$mnewsletter->id.'"';
          $db->setQuery($query);
          $db->query();
        }

        if ( ($newsletter_delay != '') && ($newsletter_delay != 0) && ($newsletter_delay != '0')) {
          sleep($newsletter_delay);
        }
      }
			if ($error_report != '') {
				$target_file = JPATH_ADMINISTRATOR.DS."components/com_nspro/error_report.txt";
				$file = fopen($target_file, "a");
				if ($file !== false) {
					fwrite($file, $error_report);
					fclose($file);
				}
      }
      if ($applySent == true) {
        $query = 'UPDATE `#__nspro_newsletters` SET `is_scheduled` = "0", `sent` = "1", `datetime` = "'.date('Y-m-d H:i:s').'" WHERE `id` = "'.$mnewsletter->id.'"';
        $db->setQuery($query);
        $db->query();
      }
    }
  }
}

?>